perm filename DEBUG.SAI[PNT,HE]2 blob sn#528552 filedate 1980-08-05 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00007 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	ENTRY
C00007 00003	! dbinit, rtn10,rtn10offset,rstrpos
C00011 00004	! break_at, unbreak_at, breakdebug
C00013 00005	! nocrlf, showtext, textdebug, trapsdebug
C00016 00006	! !!go, p!!sstep,p!!xstep,haltdebug
C00030 00007	! pbreak,debugloop
C00034 ENDMK
C⊗;
ENTRY;
BEGIN "DEBUG"
DEFINE $DEBUG=TRUE;
REQUIRE "HEADER.SAI" SOURCE_FILE;

INTEGER NEWPCDBUF;	! new pcode buffer for pcode generated/interpreted
			  while debugging;
INTEGER $COORD,$OFFSET;	! breakpoint coord. and offset;
RPTR(SYMBOL)$WHERE;	! breakpoint proc;


RPTR(EXPR$)PROCEDURE DBEX$2(INTEGER ARG1,INSTR,TXT,PROCREF);
	BEGIN
	RPTR(EXPR$)PTR;RPTR(DBEXPR)DBR;
	INTEGER ARRAY TXTPOS,COORD,TRAPS[1:1];RPTR (BLOCKREC) ARRAY BLOCK[1:1];
	EXPR$:DBEXPR[PTR←EXPR$2(ARG1,instr)]←(DBR←NEW_RECORD(DBEXPR));
	TXTPOS[1]←TXT;COORD[1]←(INSTR ASH 12)+PROCREF; BLOCK[1]←CURBLOCK; 
	MEMORY[LOCATION(txtpos)] ↔ MEMORY[LOCATION(DBEXPR:txtpos[DBR])];
	MEMORY[LOCATION(coord)] ↔ MEMORY[LOCATION(DBEXPR:coord[DBR])];
	MEMORY[LOCATION(block)] ↔ MEMORY[LOCATION(DBEXPR:block[DBR])];
	DBEXPR:#COORD[DBR]←1;
	RETURN(PTR);
	END;

DEFINE #BMARK= '240000;
DEFINE #EMARK= '020000;

INTERNAL RPTR(EXPR$) PROCEDURE MARK(INTEGER INSTR,TXTPOS);
	BEGIN
 	RPTR (EXPR$) ARRAY TEMP[1:3];INTEGER OFF;
	OFF←IF CURPROC THEN IF $COMPILE THEN $SYMOFF ELSE $SYMOFF-1 ELSE 0;
	TEMP[1]← EXPR$2(#BMARK LOR OFF,INSTR);
	TEMP[2]←$$PCODE;
	TEMP[3]←DBEX$2(#EMARK LOR OFF,INSTR,TXTPOS,
			IF REFPROC THEN SYMBOL:OFFSET[REFPROC] ELSE 0);
	REFPROC←NULL_RECORD;
	RETURN ($AAPPEND(TEMP));
	END;

! offset & coord in the same word
0000000000000000000000 00000000000000
coord                  offset	
;
! dbinit, rtn10,rtn10offset,rstrpos;

INTERNAL PROCEDURE DBINIT;
	BEGIN
	! create $$DEBUG from $$pcode, order it with respect to coord numbers,
	  and save pcdpos;
	INTEGER PCSIZE,SSIZE;
	PCSIZE←EXPR$:#BODY[$$PCODE];
	SSIZE←DBEXPR:#COORD[($$DEBUG←EXPR$:DBEXPR[$$PCODE])];
		BEGIN "a"
		INTEGER ARRAY PCDPOS,TXTPOS,COORD,TRAPS[1:SSIZE];
		RPTR(BLOCKREC)ARRAY BLOCK[1:SSIZE];INTEGER I,J,K;
		J←0;
		FOR I←1 STEP 1 UNTIL PCSIZE DO
		   IF EXPR$:BODY[$$PCODE][i]≥ #BMARK THEN PCDPOS[J←J+1]←I;
		IF J≠SSIZE THEN ERROR("DEBUG INIT error");
		MEMORY[LOCATION(PCDPOS)] ↔ MEMORY[LOCATION(DBEXPR:PCDPOS[$$DEBUG])];
	! ordering of txtpos, coord, and block;
		FOR I←1 STEP 1 UNTIL SSIZE DO
			BEGIN
			J← DBEXPR:COORD[$$DEBUG][I] ASH -12;
			TXTPOS[J]←DBEXPR:TXTPOS[$$DEBUG][I];
			BLOCK[J]←DBEXPR:BLOCK[$$DEBUG][I];
			COORD[J]←DBEXPR:COORD[$$DEBUG][I];
			END;
		MEMORY[LOCATION(COORD)] ↔ MEMORY[LOCATION(DBEXPR:COORD[$$DEBUG])];
		MEMORY[LOCATION(TXTPOS)] ↔ MEMORY[LOCATION(DBEXPR:TXTPOS[$$DEBUG])];
		MEMORY[LOCATION(BLOCK)] ↔ MEMORY[LOCATION(DBEXPR:BLOCK[$$DEBUG])];
		MEMORY[LOCATION(TRAPS)] ↔ MEMORY[LOCATION(DBEXPR:TRAPS[$$DEBUG])];
		END "a";
	DBEXPR:BODY[$$DEBUG]←$CLNSAVE;
	IF CURPROC THEN PROC:DBEXPR[SYMBOL:OBJECT[CURPROC]]←$$DEBUG;
	END;

INTERNAL BOOLEAN PROCEDURE RTN10;
	RETURN(!DEBUG AND ¬!!DEBUGGING AND ¬CURPROC
		AND ((DBEXPR:COORD[$$DEBUG][1] LAND '7777) OR
			DBEXPR:#COORD[$$DEBUG]>1));

	! return the restarting position in pcode (in words) relative to the
	beginning of pcode or of procedure pcode;
	! remember to take care of PHALT,offset,coord in front of instruction;
INTEGER PROCEDURE RSTRPOS(RPTR(DBEXPR) DEBG;INTEGER COORD,OFFSET);
	BEGIN
	IF COORD>DBEXPR:#COORD[DEBG] THEN ERROR(":: coordinate too big.");
	IF COORD=1 AND OFFSET THEN ERROR("can't break first instruction of proc.");
	RETURN(DBEXPR:PCDPOS[DEBG][COORD] -1 + (IF OFFSET THEN -4 ELSE 3));
	END;
! break_at, unbreak_at, breakdebug;

RPTR(EXPR$)PROCEDURE BREAK_AT(INTEGER OFFSET,POS11,COORD;RPTR(DBEXPR)DEBG);
	BEGIN
	$$PCODE←EXPR$3(XPBREAK,OFFSET,POS11);
	DBEXPR:TRAPS[DEBG][COORD]←XPBREAK;
	END;

RPTR(EXPR$)PROCEDURE UNBREAK_AT(INTEGER OFFSET,POS11,COORD;RPTR(DBEXPR)DEBG);
	BEGIN
	IF DBEXPR:TRAPS[DEBG][COORD]≠XPBREAK 
	   THEN PRINT("non_existing TRAP",CRLF)
	   ELSE BEGIN 
		DBEXPR:TRAPS[DEBG][COORD]←0;
		$$PCODE←EXPR$3(XUBREAK,OFFSET,POS11);
		END;
	END;

INTERNAL PROCEDURE BREAKDEBUG(BOOLEAN INSERT);
	BEGIN
	INTEGER BPC,OFFSET,POS11;RPTR(SYMBOL)WHERE;rptr(dbexpr)debg;
	WORD_READ("(");if WHERE←PROCNAME_READ then WORD_READ(",");
	BPC←GT_ZERO_READ;WORD_READ(")");
	DEBG← IF WHERE THEN PROC:DBEXPR[SYMBOL:OBJECT[WHERE]] ELSE $$DEBUG;
	IF DEBG=NULL_RECORD THEN ERROR("cannot break "&symbol:pname[where]);
	OFFSET← IF WHERE THEN SYMBOL:OFFSET[WHERE] ELSE 0;
	POS11←RSTRPOS(DEBG, BPC, OFFSET);	! coordinate of the pcode (in word);
	IF BPC > DBEXPR:#COORD[DEBG]
	   THEN ERROR(BPC,": non_existing coordinate !")
	   ELSE IF INSERT THEN	BREAK_AT(OFFSET,POS11,BPC,DEBG)
		ELSE UNBREAK_AT(OFFSET,POS11,BPC,DEBG);
	END;
! nocrlf, showtext, textdebug, trapsdebug;

RECURSIVE STRING PROCEDURE NOCRLF(STRING S);
 RETURN(IF LENGTH(S)<2 THEN S
	ELSE IF EQU(S[1 FOR 2],CRLF) THEN NOCRLF(S[3 TO ∞])
	     ELSE S);


PROCEDURE SHOWTEXT(RPTR(SYMBOL)WHERE;INTEGER LOW, UP_COUNT(0));
	BEGIN
	INTEGER UPPER,IC,maxc;
	RPTR(DBEXPR)DEBG;STRING BODY;
	UPPER← IF LOW ≤ UP_COUNT THEN UP_COUNT
		ELSE IF UP_COUNT=0 THEN LOW ELSE LOW+UP_COUNT-1;
	DEBG← IF WHERE THEN PROC:DBEXPR[SYMBOL:OBJECT[WHERE]] ELSE $$DEBUG;
	IF DEBG=NULL_RECORD THEN ERROR("cannot show text of "&symbol:pname[where]);
	BODY ← DBEXPR:BODY[DEBG];
	IF UPPER > (MAXC←DBEXPR:#COORD[DEBG])
	   THEN	BEGIN
		PRINT(UPPER,":: coordinate is too big.");
		UPPER←MAXC;
		END;
	PRINT(CRLF);
	FOR IC←LOW STEP 1 UNTIL UPPER DO
		PRINT(IF WHERE THEN SYMBOL:PNAME[WHERE]&" " ELSE "",
			  IC,":	",NOCRLF(BODY[DBEXPR:TXTPOS[DEBG][IC]+1
			  TO IF IC≠MAXC THEN DBEXPR:TXTPOS[DEBG][IC+1]
				ELSE ∞]),CRLF)
	END;


INTERNAL PROCEDURE TEXTDEBUG;
	BEGIN
	INTEGER LOW,UPPER;RPTR(SYMBOL) WHERE;
	IF IS_TOKEN("(")
	   THEN BEGIN
		IF WHERE←PROCNAME_READ THEN WORD_READ(",");
		LOW←GT_ZERO_READ; WORD2_READ(",",")","TEXT");
		IF TOKEN="," THEN BEGIN UPPER←GT_ZERO_READ; WORD_READ(")");END 
		   ELSE UPPER←0;
		END
	   ELSE BEGIN LOW←$COORD;UPPER←0;WHERE←$WHERE;END;
	SHOWTEXT(WHERE,LOW,UPPER);
	END;

INTERNAL RECURSIVE PROCEDURE TRAPSDEBUG(RPTR(SYMBOL) WHERE(NULL_RECORD));
	BEGIN
	INTEGER I,N,OFF;RPTR(DBEXPR) DEBG;
	DEBG← IF WHERE THEN PROC:DBEXPR[SYMBOL:OBJECT[WHERE]] ELSE $$DEBUG;
	IF DEBG=NULL_RECORD THEN RETURN;
	N←DBEXPR:#COORD[DEBG];
	FOR I←1 STEP 1 UNTIL N DO
	    BEGIN "TR"
	    IF DBEXPR:TRAPS[DEBG][I] THEN SHOWTEXT(WHERE, I);
	    IF OFF←DBEXPR:COORD[DEBG][I] LAND '7777
		THEN TRAPSDEBUG(CHECKOFF (OFF));
	    END "TR";
	 END;
! !!go, p!!sstep,p!!xstep,haltdebug;

INTERNAL PROCEDURE HALTDEBUG;
	BEGIN
	$$PCODE←EXPR$3(XPHALT,IF CURPROC THEN SYMBOL:OFFSET[CURPROC] ELSE 0,INSTR_N);	
	END;

INTERNAL PROCEDURE RESTARTDEBUG;
	BEGIN
	IF $OFFSET THEN ERROR("cannot RESTART inside a procedure")
	   ELSE $EXECUTE(EXPR$1(XPRESTART));
	END;

PROCEDURE P!!GO(INTEGER COORD,OFFSET);
	$EXECUTE(EXPR$2(XCNTRL,CNTRG));

PROCEDURE P!!STEP(INTEGER COORD,OFFSET);
	$EXECUTE(EXPR$2(XCNTRL,CNTRS));

PROCEDURE P!!GSTEP(INTEGER COORD,OFFSET);
	$EXECUTE(EXPR$2(XCNTRL,CNTRX));
! pbreak,debugloop;

INTERNAL PROCEDURE PBREAK;
	BEGIN
	INTEGER I,OFFSET;
	SETPCDBUF(IF ¬!!DEBUGGING THEN (NEWPCDBUF← OLDPCDBUF+PSIZE*2)
				  ELSE	NEWPCDBUF);
	$OFFSET←GETIN;$COORD←GETIN;
	IF NOT !DEBUG	
	   THEN	PRINT("HALT at : "&CVS($COORD)&
			(if $offset then " offset "&CVS($OFFSET) ELSE "")&CRLF)
	   ELSE SHOWTEXT($where←(IF $OFFSET THEN CHECKOFF($OFFSET) ELSE NULL_RECORD),
			 $COORD);
	DEBUGLOOP;
	END;


INTERNAL PROCEDURE DEBUGLOOP;
	BEGIN
	STRING S;BOOLEAN RSTR;
	!!DEBUGGING←TRUE;RSTR←FALSE;
     DO BEGIN
	PRINT(CRLF,":*: ");ASKUSER; S← _SKIP_ ;
	IF S="G" OR S="g"  THEN BEGIN P!!GO($COORD,$OFFSET);DONE;END;
	IF S="X" OR S="x" 
	   THEN IF ¬!DEBUG
		   THEN BEGIN PRINT("Only ↑G can help you!");CONTINUE;end
	   ELSE	BEGIN P!!GSTEP($COORD,$OFFSET);DONE;END;
	IF S="S" OR S="s"
	   THEN IF ¬!DEBUG
		   THEN BEGIN PRINT("Only ↑G can help you!");CONTINUE;end
	   ELSE	BEGIN P!!STEP($COORD,$OFFSET);DONE;END;
	STOKEN← FALSE;
 	GTOKEN;
	IF  EQU(TOKEN,"!!GO") THEN BEGIN P!!GO($COORD,$OFFSET);DONE;END;
	IF ¬!DEBUG THEN BEGIN PRINT("Only !!go can help you!");CONTINUE;END;
	IF EQU(TOKEN,"!!GSTEP") THEN BEGIN P!!GSTEP($COORD,$OFFSET);DONE;END;
	IF EQU(TOKEN,"!!STEP") THEN BEGIN P!!STEP($COORD,$OFFSET);DONE;END;
	IF EQU(TOKEN,"RESTART") THEN BEGIN RESTARTDEBUG;RSTR←TRUE;DONE;END;
	STOKEN←TRUE;
	PREPARSE;
	CURBLOCK←DBEXPR:BLOCK[IF $WHERE THEN PROC:DBEXPR[symbol:object[$WHERE]]
				 ELSE $$DEBUG][$COORD];
	PARSE;			! parses the instruction;
	CHKESC_I;		! check if escape_I was typed ;
	IF NOT FINAL THEN SEMICOL_READ;
	IF !LINE THEN PRINT(CRLF,"LAST STATEMENT: ",$CLNSAVE);
	END
 UNTIL FALSE;
	IF RSTR THEN RSTR11 ELSE CONTNU11;
	END;

END "DEBUG"